/**
 * Copyright (C) 2009+ Spark Zheng
 *
 * @file        src/libdserver.h 
 * @date        2010-04-26
 * @brief	general_network
 * @see         dserver
 * @history
 */

#ifndef _DSERVER_LIBDSERVER_H
#define _DSERVER_LIBDSERVER_H

#ifdef __cplusplus
extern "C" {
#endif

#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <pthread.h>
#include <event.h>
#include <dlib/global.h>

#include "utils.h"
#include "connection.h"
#include "prot_types.h"
#include "mont_types.h"
#include "filt_types.h"
#include "dserver_log.h"
#include "dserver_errno.h"

#ifndef DSERVER_MONITOR_PRIORITY
#define DSERVER_MONITOR_PRIORITY	7
#endif
#ifndef DSERVER_PROT_PRIORITY
#define DSERVER_PROT_PRIORITY		4
#endif
#ifndef DSERVER_PROT_TCP_NODELAY
#define DSERVER_PROT_TCP_NODELAY	1
#endif
#ifndef DSERVER_PROT_TCP_KEEPALIVE
#define DSERVER_PROT_TCP_KEEPALIVE	1
#endif
#ifndef DSERVER_PROT_MAX_RX_BUF
#define DSERVER_PROT_MAX_RX_BUF		0
#endif
#ifndef DSERVER_PROT_MAX_TX_BUF
#define DSERVER_PROT_MAX_TX_BUF		0
#endif

#ifndef DSERVER_PROT_NAME
#define DSERVER_PROT_NAME		"dserver"
#endif
#ifndef DSERVER_PROT_MAXCONN
#define DSERVER_PROT_MAXCONN		4096
#endif

/**
 * a dserver handler include session_init,
 * session_worker, session_exit callbacks.
 * session_init called at connection-made,
 * session_worker called at data-received,
 * session_exit called at connection-closed.
 */
typedef int		(*dserver_session_init_fn)(void *arg);
typedef prot_ret_t	(*dserver_session_worker_fn)(void *arg);
typedef void		(*dserver_session_exit_fn)(void *arg);

typedef struct dserver_handler		dserver_handler_t;

/** libdserver APIs */
/**
 * dserver_set_handlers
 * @brief set callbacks for current handler
 * @param handler: current handler
 * @param init_cb: session_init callback
 * @param worker_cb: session_worker callback
 * @param exit_cb: session_exit callback
 */
extern int dserver_set_handlers(dserver_handler_t *handler,
		dserver_session_init_fn init_cb,
		dserver_session_worker_fn worker_cb,
		dserver_session_exit_fn exit_cb);

/**
 * dserver_tcpserver_init
 * @brief init a tcp server
 * @return tcp server handler or NULL on error
 * @param host: listened on host & port
 * @param port: listened on host & port
 * @param timeout: protocol timeout
 */
extern dserver_handler_t *dserver_tcpserver_init(const char *host,
		in_port_t port, uint16_t timeout);

/**
 * dserver_tcpserver_exit
 * @brief destroy a tcp server
 * @param handler: tcp server handler
 */
extern void dserver_tcpserver_exit(dserver_handler_t *handler);

/**
 * dserver_tcpserver_run
 * @brief running a tcp server forever
 * @return < 0 error
 * @param handler: tcp server handler
 */
extern int dserver_tcpserver_run(dserver_handler_t *handler);

/**
 * dserver_tcpclient_init
 * @brief init a tcp client
 * @return tcp client fd with snd/rcv timeout sockopt
 * @param host: connecting to host & port
 * @param port: connecting to host & port
 * @param timeout: socket read/write timeout
 */
extern int dserver_tcpclient_init(const char *host, in_port_t port, uint16_t timeout);

/**
 * dserver_tcpclient_exit
 * @brief close tcp socket
 * @param fd: tcp socket
 */
extern int dserver_tcpclient_exit(int fd);

extern ssize_t dserver_tcpdata_write(int sockfd, const char *buf,
		size_t buf_len, uint16_t timeo);

extern ssize_t dserver_tcpdata_writev(int sockfd, const struct iovec *vec,
		uint16_t vec_nr, uint16_t timeo);

extern ssize_t dserver_tcpdata_read(int sockfd, char *buf, size_t buf_len,
		uint16_t timeo);

extern ssize_t dserver_tcpdata_readv(int sockfd, struct iovec *vec,
		uint16_t vec_nr, uint16_t timeo);

extern ssize_t dserver_tcpdata_sendfile(int infd, int outfd, size_t nr,
		off_t *from, off_t *to);

/**
 * dserver_udpserver_init
 * @brief init a udp server
 * @return udp server handler or NULL on error
 * @param host: listened on host & port
 * @param port: listened on host & port
 * @param timeout: protocol timeout
 */
extern dserver_handler_t *dserver_udpserver_init(const char *host,
		in_port_t port, uint16_t timeout);

/**
 * dserver_udpserver_exit
 * @brief destroy a tcp server
 * @return udp server handler or NULL on error
 * @param handler: udp server handler
 */
extern void dserver_udpserver_exit(dserver_handler_t *handler);

/**
 * dserver_udpserver_run
 * @brief running a udp server forever
 * @param handler: udp server handler
 */
extern int dserver_udpserver_run(dserver_handler_t *handler);

/**
 * dserver_udpclient_init
 * @brief init a udp client
 * @return udp client fd with snd/rcv timeout sockopt
 * @param host: sendto host & port
 * @param port: sendto host & port
 * @param timeout: socket read/write timeout
 */
extern int dserver_udpclient_init(const char *host, in_port_t port, uint16_t timeout);

/**
 * dserver_udpclient_exit
 * @brief close udp socket
 * @param fd: udp socket
 */
extern int dserver_udpclient_exit(int fd);

extern ssize_t dserver_udpdata_write(int sockfd, const char *buf,
		size_t buf_len, uint16_t timeo);

extern ssize_t dserver_udpdata_writev(int sockfd, const struct iovec *vec,
		uint16_t vec_nr, uint16_t timeo);

extern ssize_t dserver_udpdata_read(int sockfd, char *buf, size_t buf_len,
		uint16_t timeo);

extern ssize_t dserver_udpdata_readv(int sockfd, struct iovec *vec,
		uint16_t vec_nr, uint16_t timeo);

extern ssize_t dserver_udpdata_sendfile(int infd, int outfd, size_t nr,
		off_t *from, off_t *to);

#ifdef __cplusplus
}
#endif
#endif
